package com.htstar.ovms.device.controller;

import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.htstar.ovms.admin.api.entity.EtpInfo;
import com.htstar.ovms.admin.api.entity.SysDictItem;
import com.htstar.ovms.admin.api.feign.EtpInfoFeign;
import com.htstar.ovms.admin.api.feign.SysDictFeign;
import com.htstar.ovms.admin.api.vo.EtpInfoSVo;
import com.htstar.ovms.common.core.i18n.MsgCode;
import com.htstar.ovms.common.core.util.OvmDateUtil;
import com.htstar.ovms.common.core.util.R;
import com.htstar.ovms.common.excel.util.ExcelHandler;
import com.htstar.ovms.common.log.annotation.SysLog;
import com.htstar.ovms.common.minio.service.MinioTemplate;
import com.htstar.ovms.common.security.util.SecurityUtils;
import com.htstar.ovms.device.api.dto.*;
import com.htstar.ovms.device.api.entity.CarAlarmMothReport;
import com.htstar.ovms.device.api.entity.DeviceAlarm;
import com.htstar.ovms.device.api.entity.ExportRecord;
import com.htstar.ovms.device.api.vo.AreaListVo;
import com.htstar.ovms.device.api.vo.CarSecurityAlarmVO;
import com.htstar.ovms.device.api.vo.DeviceAlarmVO;
import com.htstar.ovms.device.api.vo.MonitoringVO;
import com.htstar.ovms.device.handle.event.AlarmExcelExportEvent;
import com.htstar.ovms.device.service.DeviceAlarmService;
import com.htstar.ovms.device.service.ExportRecordService;
import com.htstar.ovms.device.util.AnalysisSalseTask;
import com.htstar.ovms.device.util.PoiExcelUtil;
import com.htstar.ovms.enterprise.api.vo.AlarmDataVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;


/**
 * 设备警情
 *
 * @author wj
 * @date 2020-06-12 11:38:07
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/devicealarm")
@Api(value = "devicealarm", tags = "设备警情管理/Equipment alarm management")
public class DeviceAlarmController {

    private final DeviceAlarmService deviceAlarmService;

    private final SysDictFeign sysDictFeign;

    @Autowired
    MinioTemplate minioTemplate;

    @Autowired
    private EtpInfoFeign etpInfoFeign;

    @Autowired
    private ExportRecordService exportRecordService;

    @Autowired
    private ApplicationEventPublisher publisher;

    /**
     * 通过设备编号查询警情信息
     *
     * @param page 分页对象
     * @return
     */
    @ApiOperation(value = "分页查询/Paging query", notes = "分页查询")
    @PostMapping("/page")
    public R<Page<DeviceAlarmVO>> getDeviceAlarmPage(@RequestParam(value = "page") Page page,
                                                     @RequestParam("deviceSn") String deviceSn,
                                                     @RequestParam(value = "startTime", required = false) String startTime
            , @RequestParam(value = "endTime", required = false) String endTime
            , @RequestParam(value = "type", required = false) Integer type) {
        return R.ok(deviceAlarmService.getAlarmInfoByDeviceSnPage(page, deviceSn, startTime, endTime, type));
    }


    /**
     * 通过id查询设备警情
     *
     * @param id id
     * @return R
     */
    @ApiOperation(value = "通过id查询/Query by id", notes = "通过id查询")
    @GetMapping("/{id}")
    public R getById(@PathVariable("id") Integer id) {
        return R.ok(deviceAlarmService.getById(id));
    }

    /**
     * 新增设备警情
     *
     * @param deviceAlarm 设备警情
     * @return R
     */
    @ApiOperation(value = "新增设备警情/New equipment alarm", notes = "新增设备警情")
    @SysLog("新增设备警情")
    @PostMapping
    @PreAuthorize("@pms.hasPermission('device_devicealarm_add')")
    public R save(@RequestBody DeviceAlarm deviceAlarm) {

        return R.ok(deviceAlarmService.save(deviceAlarm));
    }

    /**
     * 修改设备警情
     *
     * @param deviceAlarm 设备警情
     * @return R
     */
    @ApiOperation(value = "修改设备警情/Modify equipment alarm", notes = "修改设备警情")
    @SysLog("修改设备警情")
    @PutMapping
    @PreAuthorize("@pms.hasPermission('device_devicealarm_edit')")
    public R updateById(@RequestBody DeviceAlarm deviceAlarm) {
        return R.ok(deviceAlarmService.updateById(deviceAlarm));
    }

    /**
     * 通过id 逻辑删除设备警情
     *
     * @param id id
     * @return R
     */
    @ApiOperation(value = "通过id 逻辑删除设备警情/Delete device alarms through id logic", notes = "通过id 逻辑删除设备警情")
    @SysLog("通过id 逻辑删除设备警情")
    @DeleteMapping("/{id}")
//    @PreAuthorize("@pms.hasPermission('device_devicealarm_del')" )
    public R removeById(@PathVariable(value = "id") Integer id) {
        DeviceAlarm deviceAlarm = new DeviceAlarm();
        deviceAlarm.setId(id);
        deviceAlarm.setIsDel(1);
        return R.ok(deviceAlarmService.updateById(deviceAlarm));
    }

    /**
     * app 安防报警
     */
    @ApiOperation(value = "安防报警/Security alarm", notes = "安防报警")
    @PostMapping("/getCarSecurityAlarmPage")
    public R<Page<CarSecurityAlarmVO>> getCarSecurityAlarmPage(@RequestBody CarSecurityAlarmDTO carSecurityAlarmDTO) {
        return R.ok(deviceAlarmService.getCarSecurityAlarmPage(carSecurityAlarmDTO));
    }

    /**
     * 根据类型和时间查看报警数据
     */
    @ApiOperation(value = "根据类型和时间查看报警数据/View alarm data according to type and time", notes = "根据类型和时间查看报警数据")
    @PostMapping("/getAlarmByTypeAndTimePage")
    public R<Page<DeviceAlarmVO>> getAlarmByTypeAndTimePage(@RequestBody CarSecurityAlarmDTO carSecurityAlarmDTO) throws Exception {
        return R.ok(deviceAlarmService.getAlarmByTypeAndTimePage(carSecurityAlarmDTO));
    }

    @ApiOperation(value = "大量导出报警数据报表/Export a large number of alarm data reports", notes = "大量导出报警数据报表")
    @PostMapping("/exportgetAlarmByTypeAndTime")
    public R hugeExcelExportAlarm(@RequestBody CarSecurityAlarmDTO carSecurityAlarmDTO) {
        Integer etpId = SecurityUtils.getUser().getEtpId();
        if (carSecurityAlarmDTO.getEtpId() == null) carSecurityAlarmDTO.setEtpId(etpId);
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(carSecurityAlarmDTO.getEtpId());
        currentAndParents1.forEach(etpInfoSVo -> {
            carSecurityAlarmDTO.setEtpIds(etpInfoSVo.getIds());
        });
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        RequestContextHolder.setRequestAttributes(servletRequestAttributes, true);//设置子线程共享

        //save export record
        ExportRecord exportRecord = new ExportRecord();
        exportRecord.setEtpId(etpId);
        exportRecord.setExportType(3);
        exportRecord.setExportStatus(1);
        exportRecord.setUserId(SecurityUtils.getUser().getId());
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss");
        String fileName = "安防警报_" + SecurityUtils.getUser().getId() + "_" + dtf2.format(LocalDateTime.now());
        exportRecord.setExportName(fileName);
        exportRecordService.save(exportRecord);
        carSecurityAlarmDTO.setExportId(exportRecord.getId());
        carSecurityAlarmDTO.setUserId(SecurityUtils.getUser().getId());
        carSecurityAlarmDTO.setFileName(fileName);
        try {
            publisher.publishEvent(new AlarmExcelExportEvent(this, carSecurityAlarmDTO));
        } catch (Exception e) {
            log.error("发布警情报表导出错误");
        }

        return R.ok(MsgCode.EXPORTING.msg());
    }

    //    /**
//     * 导出报警数据报表
//     */
//    @ApiOperation(value = "导出报警数据报表", notes = "导出报警数据报表")
//    @PostMapping("/exportgetAlarmByTypeAndTime")
    public void exportgetAlarmByTypeAndTime(@RequestBody CarSecurityAlarmDTO carSecurityAlarmDTO, HttpServletResponse response) {
        String exportName = null;
        try {
            exportName = "安防警报" + new String(URLEncoder.encode(
                    "定位信息" + OvmDateUtil.getCstNow().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
                    , "UTF-8").getBytes("UTF-8"), "ISO8859-1") + ".xlsx";
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        List<DeviceAlarmVO> alarmByTypeAndTimePage = deviceAlarmService.getAlarmByTypeAndTimeList(carSecurityAlarmDTO);
        if (CollectionUtils.isEmpty(alarmByTypeAndTimePage)) {
            return;
        }
        BigExcelWriter writer = ExcelUtil.getBigWriter("/" + exportName);
        writer.renameSheet(exportName);
        List<Map<String, Object>> rows = new ArrayList<>();
        for (DeviceAlarmVO deviceAlarm : alarmByTypeAndTimePage) {
            Map<String, Object> row = new LinkedHashMap<>();

            SysDictItem dictByTypeValue = sysDictFeign.getDictByTypeValue(deviceAlarm.getAlarmType());
            row.put("企业", deviceAlarm.getEtpName() == null ? "" : deviceAlarm.getEtpName());
            row.put("设备号", deviceAlarm.getDeviceSn() == null ? "" : deviceAlarm.getDeviceSn());
            row.put("车牌号码", deviceAlarm.getLicCode() == null ? "" : deviceAlarm.getLicCode());
            row.put("警情类型", dictByTypeValue.getLabel() == null ? "" : dictByTypeValue.getLabel());
            row.put("警情开始时间", deviceAlarm.getStaTime() == null ? "" : deviceAlarm.getStaTime());
            row.put("警情发生地址", deviceAlarm.getGpsAddr() == null ? "" : deviceAlarm.getGpsAddr());
            rows.add(row);
        }
        writer.write(rows, true);

        OutputStream out = null;
        try {
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(URLEncoder.encode(
                    "定位信息" + OvmDateUtil.getCstNow().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
                    , "UTF-8").getBytes("UTF-8"), "ISO8859-1") + ".xlsx");
            out = response.getOutputStream();
            writer.flush(out, true);
        } catch (IOException e) {
            log.error("定位信息导出失败", e);
        } finally {
            writer.close();
            IoUtil.close(out);
        }
        return;
    }

    /**
     * 【车辆定位】
     * 查询监控和管理员后台定位信息列表
     */
    @ApiOperation(value = "查询监控和管理员后台定位信息列表/Query monitoring and administrator background location information list", notes = "查询监控和管理员后台定位信息列表")
    @PostMapping("/getMonitoringPage")
    public R<Page<MonitoringVO>> getMonitoringPage(@RequestBody MonitoringDTO monitoringDTO) {
        log.info("属性{}", monitoringDTO);
        return R.ok(deviceAlarmService.getMonitoringPage(monitoringDTO));
    }

    /**
     * 查询监控和管理员后台定位信息列表,不带分页
     */
    @ApiOperation(value = "查询监控和管理员后台定位信息列表,不带分页/Query monitoring and administrator background location information list, without pagination", notes = "查询监控和管理员后台定位信息列表,不带分页")
    @PostMapping("/getMonitorings")
    public R getMonitorings(@RequestBody MonitoringLatLngDTO monitoringDTO) {
        return R.ok(deviceAlarmService.getMonitorings(monitoringDTO));
    }

    /**
     * 查询地图，根据传入区域代码和类型查询子区域
     */
    @ApiOperation(value = "查询地图，根据传入区域代码和类型查询子区域/Query the map, query the sub-areas according to the incoming area code and type", notes = "查询地图，根据传入区域代码和类型查询子区域")
    @PostMapping("/arealistData")
    public R arealistData(@RequestBody AreaDTO areaDTO) {
        return R.ok(deviceAlarmService.findList(areaDTO));
    }

    /**
     * 查询地图，根据传入区域代码和类型查询子区域阶梯式
     */
    @ApiOperation(value = "查询地图，根据传入区域代码和类型查询子区域区域阶梯式/Query the map, query the sub-area according to the incoming area code and type.", notes = "查询地图，根据传入区域代码和类型查询子区域区域阶梯式")
    @GetMapping("/arealistDataPage")
    public R<List<AreaListVo>> arealistDatas() {
        return R.ok(deviceAlarmService.findLists());
    }

    /**
     * 后台定位信息导出
     */
    @ApiOperation(value = "后台定位信息导出/Background location information export", notes = "后台定位信息导出")
    @PostMapping("/exportLocationInfo")
    public void exportLocationInfo(@RequestBody(required = false) ExportMonitoringDTO monitoringDTO, HttpServletResponse response) {
        List<MonitoringVO> monitoringVOS = null;
        monitoringVOS = deviceAlarmService.exportLocationInfo(monitoringDTO);

//        if (CollectionUtils.isEmpty(monitoringVOS)) {
//            return;
//        }
//        ExcelWriter writer = ExcelUtil.getWriter(true);
//        writer.renameSheet("设备信息");
//        List<Map<String, Object>> rows = new ArrayList<>();
//        for (MonitoringVO monitoringVO : monitoringVOS) {
//            Map<String, Object> row = new LinkedHashMap<>();
//            row.put("车辆所属企业", monitoringVO.getEtpName() == null ? "" : monitoringVO.getEtpName());
//            row.put("车牌号码", monitoringVO.getLicCode() == null ? "" : monitoringVO.getLicCode());
//            row.put("经度", monitoringVO.getLng() == null ? "" : monitoringVO.getLng());
//            row.put("纬度", monitoringVO.getLat() == null ? "" : monitoringVO.getLat());
//            row.put("状态", monitoringVO.getOnline() == null ? "" : monitoringVO.getOnline() == 1 ? "在线" : "离线");
//            row.put("定位时间", monitoringVO.getGpsTime() == null ? "" : monitoringVO.getGpsTime());
//            row.put("通信时间", monitoringVO.getUpdateTime() == null ? "" : monitoringVO.getUpdateTime());
//            rows.add(row);
//        }
//        writer.write(rows, true);
//        OutputStream out = null;
//        try {
//            response.setContentType("application/vnd.ms-excel;charset=utf-8");
//            response.setHeader("Content-Disposition", "attachment;filename=" + new String(URLEncoder.encode(
//                    "定位信息" + OvmDateUtil.getCstNowDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
//                    , "UTF-8").getBytes("UTF-8"), "ISO8859-1") + ".xlsx");
//            out = response.getOutputStream();
//            writer.flush(out, true);
//        } catch (IOException e) {
//            log.error("定位信息导出失败", e);
//        } finally {
//            writer.close();
//            IoUtil.close(out);
//        }
        return;
    }

    @ApiOperation(value = "企业警情数据统计/Enterprise police data statistics", notes = "企业警情数据统计")
    @GetMapping("/getAlarmData/{etpId}/{date}")
    public R<AlarmDataVo> getAlarmData(@PathVariable("etpId") Integer etpId, @PathVariable("date") String date) {
        return R.ok(deviceAlarmService.getAlarmDataByEtpId(etpId, date));
    }

    @ApiOperation(value = "企业警情数据统计企业分级/Enterprise police data statistics enterprise classification", notes = "企业警情数据统计企业分级")
    @GetMapping("/getAlarmDataMultiEtp/{etpId}/{date}")
    R getAlarmDataMultiEtp(@PathVariable("etpId") Integer etpId, @PathVariable("date") String date) {
//        AlarmDataVo rs = deviceAlarmService.getAlarmDataMultiEtp(etpId, date);
        AlarmDataVo alarmDataByEtpId = deviceAlarmService.getAlarmDataByEtpId(etpId, date);
        return R.ok(alarmDataByEtpId);
    }


    @ApiOperation(value = "企业警情数据统计企业分级/Enterprise police data statistics enterprise classification", notes = "企业警情数据统计企业分级")
    @RequestMapping("/getAlarmDataDirect/{timeType}")
    public R<AlarmDataVo> getAlarmDataDirect(@PathVariable("timeType") Integer timeType, @RequestBody EtpInfo etpInfo) {
        R rs = deviceAlarmService.getAlarmDataDirect(timeType, etpInfo);
        return rs;
    }


    @GetMapping("/test")
    public void test() {
        //记录上线报表
        CarAlarmMothReport carAlarmMothReport = new CarAlarmMothReport();
        carAlarmMothReport.setOnline(1);
        carAlarmMothReport.setDeviceSn("4568");
        carAlarmMothReport.setLicCode("開通的ie");
        carAlarmMothReport.setMonthShort(LocalDateTime.now());
        carAlarmMothReport.setEtpId(2);
        deviceAlarmService.saveOnlineReport(carAlarmMothReport);
    }


    /**
     * 导出用户信息
     */
    @PostMapping("/exportgetAlarmByTypeAndTimes")
    public void exportUser(@RequestBody CarSecurityAlarmDTO carSecurityAlarmDTO, HttpServletResponse response) {
        // 开始时间
        long start = System.currentTimeMillis();
        carSecurityAlarmDTO.setCurrent(1);
        carSecurityAlarmDTO.setSize(10L);
        IPage<DeviceAlarmVO> userPage = null;
        try {
            userPage = deviceAlarmService.getAlarmByTypeAndTimePage(carSecurityAlarmDTO);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 总共有多少条数据
        Long total = userPage.getTotal();
        // 用户有很多，考虑2000条以上数据的导出 一个之多104w 行数据
        Long rowMaxCount = 500000L;
        // 每一次查询条数
        Long eachCount = 1000L;
        // 这里不用PageParam<User> ，为了方便自由调整查询条数
        CarSecurityAlarmDTO pages = new CarSecurityAlarmDTO();
        pages.setCurrent(1);

        // 控制list 大小
        Long listSize = 2000L;
        // list 分片的数量
        int listNums = getPageSize(total, listSize);
        List<DeviceAlarmVO> list = new ArrayList<>();

        String filepath = "";
        // 查询记录数
        //通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getBigWriter();
        String fileName = "用户信息表.xls";
        if (total <= rowMaxCount) {
            if (total <= eachCount) {
                pages.setSize(total);
                try {
                    userPage = deviceAlarmService.getAlarmByTypeAndTimePage(carSecurityAlarmDTO);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                exportExcel(userPage.getRecords(), 1, 1, response, writer);
                // 导出
                PoiExcelUtil.writeExcel(fileName, writer, response);
            } else {
                // 开启多线程查询，每eachCount(100)行数据为一个线程开始
                int pageSize = getPageSize(total, eachCount);
//                ExecutorService execservice = new ThreadPoolExecutor(4,10,200L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(10));
                ExecutorService execservice = Executors.newFixedThreadPool(15);
                try {
                    List<Callable<List<DeviceAlarmVO>>> tasks = new ArrayList<Callable<List<DeviceAlarmVO>>>();
                    for (int i = 1; i <= pageSize; i++) {
                        carSecurityAlarmDTO.setCurrent(i);
                        carSecurityAlarmDTO.setSize(eachCount);
                        Callable<List<DeviceAlarmVO>> task = new AnalysisSalseTask(deviceAlarmService, carSecurityAlarmDTO);
                        tasks.add(task);
                    }
                    List<Future<List<DeviceAlarmVO>>> futures = execservice.invokeAll(tasks);
                    if (futures != null && futures.size() > 0) {
                        for (Future<List<DeviceAlarmVO>> future : futures) {
                            list.addAll(future.get());
                        }
                    }
                    execservice.shutdown();
                    tasks.clear();
                    long end = System.currentTimeMillis();
                    System.out.println("线程查询数据用时:" + (end - start) + "ms");
                } catch (Exception e) {
                    System.out.println("多线程查询异常");
                }
                exportExcel(list, 1, 0, response, writer);
                list.clear();
                // 导出
                PoiExcelUtil.writeExcel(response, writer);
            }
        } else {
            // 分多少个 sheet
            int pageSize = getPageSize(total, rowMaxCount);
            eachCount = 1000L;
            for (int i = 1; i <= pageSize; i++) {
                list.clear();
                int size = getPageSize(rowMaxCount, eachCount);
                try {
                    ExecutorService execservice = new ThreadPoolExecutor(4, 10, 200L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(10));
                    List<Callable<List<DeviceAlarmVO>>> tasks = new ArrayList<>();
                    for (int j = 1; j <= size; j++) {
                        carSecurityAlarmDTO.setSize(eachCount);
                        carSecurityAlarmDTO.setCurrent((i - 1) * size + j);
                        Callable<List<DeviceAlarmVO>> task = new AnalysisSalseTask(deviceAlarmService, carSecurityAlarmDTO);
                        tasks.add(task);
                    }
                    List<Future<List<DeviceAlarmVO>>> futures = execservice.invokeAll(tasks);
                    if (Objects.nonNull(futures) && futures.size() > 0) {
                        for (Future<List<DeviceAlarmVO>> future : futures) {
                            list.addAll(future.get());
                        }
                    }
                    tasks.clear();
                    execservice.shutdown();
                    long end = System.currentTimeMillis();
                    System.out.println("线程查询数据用时:" + (end - start) + "ms");
                } catch (Exception e) {
                    System.out.println("多线程查询异常");
                }
                // 序号 (i-1) * rowMaxCount + 1
                int rowStart = new BigDecimal(i - 1).multiply(new BigDecimal(rowMaxCount)).add(new BigDecimal(1)).intValue();
                //方法1： 导出到一个临时文件，
                // 然后合并小于50W行的Excel到100W行为一个Excel文件,此处跳过，直接是100W行为一个文件
                // 然后将100W的每一个Excel文件进行压缩

                // 方法2：分多个sheet 导出
                // 此时达到 rowMaxCount 行数据 list 导出到excel
                exportExcel(list, rowStart, i - 1, response, writer);
                list.clear();
            }
            // 导出
            PoiExcelUtil.writeExcel(response, writer);
        }
    }

    private int getPageSize(Long total, Long eachCount) {
        int pageSize = new BigDecimal(total).divide(new BigDecimal(eachCount), 1).intValue();
        int mod = new BigDecimal(total).divideAndRemainder(new BigDecimal(eachCount))[1].intValue();
        if (mod > 0) {
            pageSize = pageSize + 1;
//            pageSize = new BigDecimal(pageSize).add(new BigDecimal(1)).intValue();
        }
        return pageSize;
    }

    /**
     * @param list     导出的数据
     * @param rowStart 开始的行数
     * @param pages    一共有多少页
     */
    private void exportExcel(List<DeviceAlarmVO> list, int rowStart, int pages, HttpServletResponse response, ExcelWriter writer) {
        // 商品导出or模板
        List<String> headerList;
        String[] header = {
                "企业", "设备号", "车牌号码", "警情类型", "警情开始时间",
                "警情发生地址"
        };
        headerList = Arrays.asList(header);
        writer.setSheet(pages);
        Sheet sheet = writer.getSheet();
        writer.merge(headerList.size() - 1, "用户信息表");
        writer.writeRow(headerList);
        for (int i = 0; i < headerList.size(); i++) {
            if (i == 19 || i == 20) {
                sheet.setColumnWidth(i, 30 * 256);
            } else {
                sheet.setColumnWidth(i, 20 * 256);
            }
        }
        // 如果要导出的数据为空，导出一个模板
        if (CollectionUtils.isEmpty(list)) {
            PoiExcelUtil.writeExcel(response, writer);
            return;
        }
        int row = rowStart;
        int size = list.size();
        for (DeviceAlarmVO deviceAlarm : list) {
            int firstRow = row + 1;
            int lastRow = row + 1;
            int col = -1;
            SysDictItem dictByTypeValue = sysDictFeign.getDictByTypeValue(deviceAlarm.getAlarmType());
            // 序号
            PoiExcelUtil.mergeIfNeed(writer, firstRow, lastRow, ++col, col, rowStart++);
            PoiExcelUtil.mergeIfNeed(writer, firstRow, lastRow, ++col, col,
                    deviceAlarm.getEtpName() == null ? "" : deviceAlarm.getEtpName());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, lastRow, ++col, col,
                    deviceAlarm.getEtpName() == null ? "" : deviceAlarm.getEtpName());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, lastRow, ++col, col,
                    deviceAlarm.getDeviceSn() == null ? "" : deviceAlarm.getDeviceSn());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, lastRow, ++col, col,
                    deviceAlarm.getLicCode() == null ? "" : deviceAlarm.getLicCode());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, lastRow, ++col, col,
                    dictByTypeValue.getLabel() == null ? "" : dictByTypeValue.getLabel());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, lastRow, ++col, col,
                    deviceAlarm.getStaTime() == null ? "" : deviceAlarm.getStaTime());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, lastRow, ++col, col,
                    deviceAlarm.getGpsAddr() == null ? "" : deviceAlarm.getGpsAddr());
            row++;
        }
    }
}
